﻿using System;
using System.Globalization;

namespace Xenta.Utils
{
    /// <summary>
    /// Represents the date and time helper.
    /// </summary>
    public static class DateHelper
    {
        #region Constants

        /// <summary>
        /// January 1, 1970 00:00:00.
        /// </summary>
        public static readonly DateTime UNIX_REF = new DateTime(1970, 1, 1, 0, 0, 0);

        #endregion

        #region Methods

        /// <summary>
        /// Determines whether the provided range is valid.
        /// </summary>
        /// <param name="from">The range "from".</param>
        /// <param name="to">The range "to".</param>
        /// <returns>true if range is valid; otherwise false.</returns>
        public static bool IsRangeValid(DateTime? from, DateTime? to)
        {
            return !from.HasValue || !to.HasValue || from.Value < to.Value;
        }

        /// <summary>
        /// Converts the date and time value to a string representaion.
        /// </summary>
        /// <param name="dt">The date and time value.</param>
        /// <param name="format">The date and time format.</param>
        /// <returns>The string representaion.</returns>
        public static string ToString(DateTime dt, string format)
        {
            return dt.ToString(format, CultureInfo.InvariantCulture);
        }

        /// <summary>
        /// Converts the string to the date and time value.
        /// </summary>
        /// <param name="s">The string representaion.</param>
        /// <param name="format">The date and time format.</param>
        /// <param name="value">When this methods returns, contains the parsed date and time value.</param>
        /// <returns>True if parsing success; otherwise false.</returns>
        public static bool TryParse(string s, string format, out DateTime value)
        {
            return DateTime.TryParseExact(s, 
                format, 
                CultureInfo.InvariantCulture, 
                DateTimeStyles.None, 
                out value);
        }

        /// <summary>
        /// Converts the string to the date and time value.
        /// </summary>
        /// <param name="s">The string representaion.</param>
        /// <param name="format">The date and time format.</param>
        /// <returns>The parsed date and time value.</returns>
        public static DateTime Parse(string s, string format)
        {
            return DateTime.ParseExact(s, format, CultureInfo.InvariantCulture, DateTimeStyles.None);
        }

        /// <summary>
        /// Converts the date and time value to local or UTC date time value.
        /// </summary>
        /// <param name="value">The date and time value.</param>
        /// <param name="kind">Indicates which kind of date is required.</param>
        /// <param name="utcOffset">The utc offsett in minutes.</param>
        /// <returns>The converted date and time value.</returns>
        public static DateTime Convert(DateTime value, DateTimeKind kind, int utcOffset)
        {
            switch(kind)
            {
                case DateTimeKind.Utc:
                    return DateTime.SpecifyKind(value.AddMinutes(-utcOffset), DateTimeKind.Utc);
                case DateTimeKind.Local:
                    return DateTime.SpecifyKind(value.AddMinutes(utcOffset), DateTimeKind.Local);
            }
            return value;
        }

        /// <summary>
        /// Converts the date to a UNIX timestamp.
        /// </summary>
        /// <param name="dt">The date to convert.</param>
        /// <returns>The number of second elapsed from January 1, 1970 00:00:00.</returns>
        public static long ToUnixTs(DateTime dt)
        {
            return (long)(dt - UNIX_REF).TotalSeconds;
        }

        /// <summary>
        /// Converts the UNIX timestamp to the date.
        /// </summary>
        /// <param name="timestamp">The number of second elapsed from January 1, 1970 00:00:00.</param>
        /// <returns>The date and time.</returns>
        public static DateTime FromUnixTs(long timestamp)
        {
            return UNIX_REF.AddSeconds(timestamp);
        }

        #endregion
    }
}
